/**
 * js 客户端缓存处理
 */
class _Cache {
    constructor() {
        this._key = "";
        this._value = undefined;
        this._relatedKey = "parentId";
        this._localCacheKeyName = "LocalCache_";
    }

    get key() {
        return this._localCacheKeyName + this._key;
    }

    get value() {
        return this._value;
    }

    load() {
        if (this.key && !this.value) {
            this._value = JSON.parse(localStorage.getItem(this.key));
        }
    }

    set(value) {
        if (value instanceof Array) {
            this._value = value;
        }

        localStorage.setItem(this.key, JSON.stringify(this.value));
    }

    /**
     * get by key(field, 列名) 按列名查询数据的方法
     * @param {any} filter 过滤器, 可以是一个过滤方法, 一个 {key: value} 类型的对象, 或者一个 id 的数组
     * @param {any} keySelector 列筛选器, 可以是一个字符串, 字符串数组, 或者方法; 字符串或者字符串数组中的值必须是当前对象集合中存在的属性值
     * @param {boolean} first 一个标识, 为 true 则只返回查询结果的第一个值
     */
    get(filter, keySelector, first) {
        if (_.isArray(this.value)) {
            var result = _.chain(this.value);
            if (_.isFunction(filter)) {
                result = result.filter(filter);
            } else if (_.isArray(filter)) {
                result = result.filter(element => _.any(filter, id => element.id == id));
            } else if (_.isObject(filter)) {
                result = result.where(filter);
            }

            if (_.isString(keySelector) || _.isArray(keySelector) || _.isFunction(keySelector)) {
                result = result.map(value => _.pick(value, keySelector));
            }

            if (_.isString(keySelector)) {
                result = result.pluck(keySelector);
            }

            if (!!first) {
                result = result.first();
            }

            return result.value();
        }
    }

    /**
     * get by id 按数据主键 Id 查询数据的方法
     * @param {any} id 数据主键, 必选, 否则返回 null
     * @param {any} keySelector 列筛选器, 可以是一个字符串, 字符串数组, 或者方法; 字符串或者字符串数组中的值必须是当前对象集合中存在的属性值
     */
    getById(id, keySelector) {
        return this.get(element => element.id == id, keySelector, true);
    }

    /**
     * get by related id 按数据对象的 relatedKay 列查询数据的方法
     * @param {any} id 要查询的 relatedKay 对应的值, relatedKey 由各缓存指定, 返回满足 relatedKey 值的所有对象
     * @param {any} keySelector 要查询的列; 可选参数, 如果不提供, 则返回满足条件的整个数据对象, 否则将只返回数据中 field 列的数组
     * @param {boolean} first 一个标识, 为 true 则只返回查询结果的第一个值
     */
    getByRelatedId(id, keySelector, first) {
        return this.get(element => element[this._relatedKey] == id, keySelector, first);
    }
}

class ScopeCache extends _Cache {
    constructor() {
        super();
        this._key = "Scope";
        this._scope = location.href;
        this._current = undefined;
    }

    get scope() {
        return this._scope;
    }

    get current() {
        return this._current;
    }

    load() {
        super.load();
        if (_.isArray(this._value)) {
            this._current = _.chain(this.value)
                .filter(x => x.scope === this.scope)
                .first()
                .value();
            if (this._current && this._current.value) {
                this._current = this._current.value;
            }
        }
    }

    set(key, value, scope) {
        if (key && value !== undefined) {
            if (scope) {
                var _page = _.chain(this.value)
                    .filter(x => x.scope === scope)
                    .first()
                    .value();
                if (_page && _page.value) {
                    _page.value[key] = value;
                } else {
                    _page = {
                        scope: scope,
                        value: {}
                    };
                    _page.value[key] = value;
                    this._value = this._value || [];
                    this._value.push({
                        scope: scope,
                        value: _page.value
                    });
                }
            } else if (!this._current) {
                this._current = {};
                this._value = this._value || [];
                this._value.push({
                    scope: this.scope,
                    value: this.current
                });
                this._current[key] = value;
            }

            super.set();
        }
    }

    get(key, scope) {
        if (key) {
            if (this._current && !scope) {
                return this._current[key];
            } else if (scope) {
                var _page = _.chain(this.value)
                    .filter(x => x.scope === scope)
                    .first()
                    .value();
                if (_page && _page.value) {
                    return _page.value[key];
                }
            }
        }
    }

    delete(key) {
        if (key && this._current) {
            delete this._current[key];
            super.set();
        }
    }
}

var localCache = new class LocalCache {
    constructor() {
        this.global = new ScopeCache();
        this.global._key = "Global";
        this.global._scope = "_global_";
        this.page = new ScopeCache();
        this.page._key = "Page";
    }

    get Globals() {
        return this.global.value;
    }

    get Pages() {
        return this.page.value;
    }

    load() {
        return Promise.resolve()
            .then(() => this.global.load())
            .then(() => this.page.load())
            .then(() => console.log("缓存加载完毕!"));
    }
}();